home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / devDiskStats.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  10KB  |  372 lines

  1. /* 
  2.  * devDiskStats.c --
  3.  *
  4.  *    Routines supporting statistics on Sprite Disk usage.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devDiskStats.c,v 9.6 91/09/10 18:19:34 rab Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <stdio.h>
  22. #include <sync.h>
  23. #include <sysStats.h>
  24. #include <devDiskStats.h>
  25. #include <user/fs.h>
  26. #include <stdlib.h>
  27. #include <list.h>
  28. #include <bstring.h>
  29. #include <string.h>
  30.  
  31. /*
  32.  * The disk stats modules cleans a linked list of registers disk to implment
  33.  * the Idle counts of devices. This list is composed of devices.
  34.  */
  35. typedef struct Device {
  36.     List_Links    links;          /* Used by the List_Links library routines.*/
  37.     Boolean (*idleCheck) _ARGS_ ((ClientData, DevDiskStats *));
  38.                                   /* Routine to check device's state. */
  39.     ClientData clientData;       /* ClientData argument to  idleCheck. */
  40.     int        type;          /* Fs_Device type of this disk. */
  41.     int        unit;              /* Fs_Device unit of this disk. */
  42.     DevDiskStats    devDiskStats;
  43.     int            refCount; /* # of times we've attached partition. */
  44. } Device;
  45.  
  46. /*
  47.  * If idleCheck functions are kept in a list pointed to by deviceListHdr and
  48.  * protected by deviceListMutex. The variable initialized set to TRUE 
  49.  * indicates the list has been initialized.
  50.  */
  51. static Sync_Semaphore deviceListMutex = Sync_SemInitStatic("devDiskStatMutex");
  52. static List_Links    deviceListHdr;
  53. static Boolean        initialized = FALSE;
  54.  
  55. /*
  56.  *----------------------------------------------------------------------
  57.  *
  58.  * Dev_GatherDiskStats --
  59.  *
  60.  *    Determine which disks are idle. This routine should be called 
  61.  *    periodically to obtain an estimate of the idle percentage of 
  62.  *    a disk.
  63.  *
  64.  * Results:
  65.  *    None.
  66.  *
  67.  * Side effects:
  68.  *    None.
  69.  *
  70.  *----------------------------------------------------------------------
  71.  */
  72. void
  73. Dev_GatherDiskStats()
  74. {
  75.     register Device *devicePtr;
  76.  
  77.     /*
  78.      * If any device has been registered do an idle check on all 
  79.      * registered devices. 
  80.      */
  81.     if (initialized) {
  82.     MASTER_LOCK(&deviceListMutex);
  83.  
  84.     LIST_FORALL(&deviceListHdr, (List_Links *) devicePtr) {
  85.         register Sys_DiskStats *stats =
  86.             &(devicePtr->devDiskStats.diskStats);
  87.     
  88.         stats->numSamples++;
  89.         if (devicePtr->idleCheck == (Boolean((*) _ARGS_ ((ClientData,
  90.         DevDiskStats *)))) NIL) {
  91.         stats->idleCount++;    /* No disk anymore. */
  92.         } else if ((devicePtr->idleCheck)(devicePtr->clientData,
  93.             &(devicePtr->devDiskStats))) {
  94.         stats->idleCount++;
  95.         }
  96.     }
  97.     MASTER_UNLOCK(&deviceListMutex);
  98.     }
  99.  
  100. }
  101.  
  102.  
  103. /*
  104.  *----------------------------------------------------------------------
  105.  *
  106.  * Dev_GetDiskStats --
  107.  *
  108.  *    Return statistics about the different disks.
  109.  *
  110.  * Results:
  111.  *    Number of statistics entries returned.
  112.  *
  113.  * Side effects:
  114.  *    Entries in *diskStatPtr filled in.
  115.  *
  116.  *----------------------------------------------------------------------
  117.  */
  118. int
  119. Dev_GetDiskStats(diskStatArr, numEntries)
  120.     Sys_DiskStats *diskStatArr;    /* Where to store the disk  stats. */
  121.     int           numEntries;    /* The number of elements in diskStatArr. */
  122. {
  123.     Device *devicePtr;
  124.     int       index;
  125.  
  126.     MASTER_LOCK(&deviceListMutex);
  127.  
  128.     /*
  129.      * Return Sys_DiskStats for all registers devices being careful not to
  130.      * overrun the callers buffer.
  131.      */
  132.     index = 0;
  133.     if (initialized) {
  134.     LIST_FORALL(&deviceListHdr, (List_Links *) devicePtr) {
  135.         if (index >= numEntries) {
  136.         break;
  137.         }
  138.         diskStatArr[index] = devicePtr->devDiskStats.diskStats;
  139.         index += 1;
  140.     }
  141.     }
  142.     MASTER_UNLOCK(&deviceListMutex);
  143.     return index;
  144. }
  145.  
  146.  
  147. /*
  148.  *----------------------------------------------------------------------
  149.  *
  150.  * DevRegisterDisk--
  151.  *
  152.  *    Register a disk with the disk stat module so that its idle 
  153.  *     percentage can be computed from period sampling and its diskStats
  154.  *    structure may available to the Dev_GetDiskStats routine.
  155.  *
  156.  * Results:
  157.  *    The initialized DevDiskStats structure for the device.
  158.  *
  159.  * Side effects:
  160.  *    The idleCheck function will be called when periodcally and should
  161.  *    return TRUE if the disk is idle. It is should be declared as follows:
  162.  *
  163.  *        Boolean idleCheck(clientData, diskStatsPtr)
  164.  *            ClientData clientData  -- The clientData argument passed
  165.  *                          to DevRegisterDevice.
  166.  *            DevDiskStats    *diskStatsPtr -- Ptr to disk stats.
  167.  *
  168.  *----------------------------------------------------------------------
  169.  */
  170.  
  171. DevDiskStats *
  172. DevRegisterDisk(devicePtr, deviceName, idleCheck, clientData)
  173.     Fs_Device    *devicePtr;    /* Fs_Device for disk. */
  174.     char    *deviceName;    /* Printable name for this device. */
  175.     Boolean    (*idleCheck) _ARGS_ ((ClientData, DevDiskStats *));
  176.                                 /* Function returning TRUE if the device
  177.                  * is idle. */
  178.     ClientData    clientData;    /* ClientData argument passed to idleCheck
  179.                  * to indicate which device. */
  180. {
  181.     Device    *newDevice, *devPtr;
  182.     Boolean    found = FALSE;
  183.  
  184.  
  185.     /*
  186.      * Allocated, initialized, and add to the callback list a Device structure
  187.      * for this device.
  188.      */
  189.     newDevice = (Device *) malloc(sizeof(Device));
  190.     List_InitElement((List_Links *) newDevice);
  191.     newDevice->idleCheck = idleCheck;
  192.     newDevice->clientData = clientData;
  193.     newDevice->type = devicePtr->type;
  194.     newDevice->unit = devicePtr->unit;
  195.     bzero((char *) &(newDevice->devDiskStats), sizeof(DevDiskStats));
  196.     Sync_SemInitDynamic(&(newDevice->devDiskStats.mutex), "DevDiskStats");
  197.     (void) strncpy(newDevice->devDiskStats.diskStats.name, deviceName,
  198.         SYS_DISK_NAME_LENGTH);
  199.     MASTER_LOCK(&deviceListMutex);
  200.     if (!initialized) {
  201.     List_Init(&deviceListHdr);
  202.     initialized = TRUE;
  203.     }
  204.     LIST_FORALL(&deviceListHdr, (List_Links *) devPtr) {
  205.     if ((devPtr->unit == devicePtr->unit) &&
  206.         (devPtr->type == devicePtr->type)) {
  207.        found = TRUE;
  208.        break;
  209.     }
  210.     }
  211.     if (found) {
  212.     devPtr->idleCheck = idleCheck;
  213.     devPtr->clientData = clientData;
  214.     } else { 
  215.     List_Insert((List_Links *) newDevice, LIST_ATREAR(&deviceListHdr));
  216.     devPtr = newDevice;
  217.     }
  218.     devPtr->refCount++;
  219.     MASTER_UNLOCK(&deviceListMutex);
  220.     if (found) {
  221.     free((char *)newDevice);
  222.     }
  223.     return &(devPtr->devDiskStats);
  224. }
  225.  
  226.  
  227. /*
  228.  *----------------------------------------------------------------------
  229.  *
  230.  * DevDiskUnregister--
  231.  *
  232.  *    Unregister a disk with the disk stat module.
  233.  *
  234.  * Results:
  235.  *    None.
  236.  *
  237.  * Side effects:
  238.  *    The idleCheck function will cease calculating for this disk.
  239.  *
  240.  *----------------------------------------------------------------------
  241.  */
  242. void
  243. DevDiskUnregister(diskStatsPtr)
  244.     DevDiskStats    *diskStatsPtr;
  245. {
  246.     Device        *devPtr;
  247.     Boolean        found = FALSE;
  248.  
  249.  
  250.     /*
  251.      * Allocated, initialized, and add to the callback list a Device structure
  252.      * for this device.
  253.      */
  254.     MASTER_LOCK(&deviceListMutex);
  255.     if (!initialized) {
  256.     MASTER_UNLOCK(&deviceListMutex);
  257.     return;
  258.     }
  259.     LIST_FORALL(&deviceListHdr, (List_Links *) devPtr) {
  260.     if (diskStatsPtr == &(devPtr->devDiskStats)) {
  261.        found = TRUE;
  262.        break;
  263.     }
  264.     }
  265.     if (found) {
  266.     /*
  267.      * For stupid reasons to do with spritemon, we're not allowed to
  268.      * free up this space.  Once a disk is noticed by the stat stuff, the
  269.      * user interface doesn't want to see it go away.
  270.      */
  271.     devPtr->refCount--;
  272.     if (devPtr->refCount == 0) {
  273.         devPtr->idleCheck = (Boolean((*) _ARGS_ ((ClientData,
  274.         DevDiskStats *)))) NIL;
  275.         devPtr->clientData = (ClientData) NIL;
  276.     }
  277.     }
  278.     MASTER_UNLOCK(&deviceListMutex);
  279.     return;
  280. }
  281.  
  282.  
  283. /*
  284.  * Temporary call-back for printing io statistics for recovery.
  285.  */
  286. Timer_QueueElement    ioStatElement;
  287. Boolean            getIOStats = FALSE;
  288.  
  289. /*ARGSUSED*/
  290. void
  291. DevPrintIOStats(time, clientData)
  292.     Timer_Ticks    time;
  293.     ClientData    clientData;
  294. {
  295.     Sys_DiskStats    diskStats[10];
  296.     int            numStats;
  297.     int            i;
  298.  
  299.     /* print stuff */
  300.     numStats = Dev_GetDiskStats(diskStats, 10 * sizeof (Sys_DiskStats));
  301.     printf("IO STATS:\n");
  302.     for (i = 0; i < numStats; i++) {
  303.     printf("name: %s\n", diskStats[i].name);
  304.     printf("controllerID: %d\n", diskStats[i].controllerID);
  305.     printf("numSamples: %d\n", diskStats[i].numSamples);
  306.     printf("idleCount: %d\n", diskStats[i].idleCount);
  307.     printf("diskReads: %d\n", diskStats[i].diskReads);
  308.     printf("diskWrites: %d\n", diskStats[i].diskWrites);
  309.     }
  310.     printf("\n");
  311.  
  312.     if (getIOStats) {
  313.     Timer_ScheduleRoutine(&ioStatElement, TRUE);
  314.     }
  315.     return;
  316. }
  317.  
  318.  
  319. /*
  320.  *----------------------------------------------------------------------
  321.  *
  322.  * Dev_StartIOStats --
  323.  *
  324.  *    Start up the kernel's periodic printing of io stats.
  325.  *    Temporary routine for recovery statistics.
  326.  *
  327.  * Results:
  328.  *    None.
  329.  *
  330.  * Side effects:
  331.  *    Call-back routine scheduled.
  332.  *
  333.  *----------------------------------------------------------------------
  334.  */
  335. void
  336. Dev_StartIOStats()
  337. {
  338.     ioStatElement.routine = DevPrintIOStats;
  339.     ioStatElement.clientData = 0;
  340.     ioStatElement.interval = timer_IntOneSecond * 10;
  341.     getIOStats = TRUE;
  342.     Timer_ScheduleRoutine(&ioStatElement, TRUE);
  343.  
  344.     return;
  345. }
  346.  
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * Dev_StopIOStats --
  352.  *
  353.  *    Stop the kernel's periodic printing of io stats.
  354.  *    Temporary routine for recovery statistics.
  355.  *
  356.  * Results:
  357.  *    None.
  358.  *
  359.  * Side effects:
  360.  *    Call-back routine descheduled.
  361.  *
  362.  *----------------------------------------------------------------------
  363.  */
  364. void
  365. Dev_StopIOStats()
  366. {
  367.     getIOStats = FALSE;
  368.     (void) Timer_DescheduleRoutine(&ioStatElement);
  369.  
  370.     return;
  371. }
  372.